package com.kylin.shared.exception;

import com.kylin.shared.common.consts.Constants;
import com.kylin.shared.enums.ResultCodeEnum;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

/**
 * 系统异常统一拦截处理类
 * @author Damon S.
 */
@Slf4j
@ControllerAdvice
public final class KylinErrorHandler {

    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(BusinessException.class)
    public ErrorResult notExpected(BusinessException e) {
        log.error(Constants.ERROR_PROCESS);
        return new ErrorResult(e.getCode(), e.getMessage(), BusinessException.class);
    }

    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(SystemException.class)
    public ErrorResult notExpected(SystemException e) {
        log.error(Constants.ERROR_PROCESS);
        return new ErrorResult(e.getCode(), e.getMessage(), SystemException.class);
    }

    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler
    public ErrorResult outOfControl(Throwable t) {
        log.error(Constants.ERROR_PROCESS);
        return new ErrorResult(ResultCodeEnum.INTERNAL_ERROR.getCode(), t.getMessage(), t.getClass());
    }

    @Value
    private static class ErrorResult {
        Integer code;
        String message;
        String throwableName;
        String traceId;

        private ErrorResult(Integer code, String message, Class<? extends Throwable> clazz) {
            this.code = code;
            this.message = message;
            this.throwableName = clazz.getName();
            this.traceId = MDC.get(Constants.LOG_TRACE_ID);
        }
    }
}